﻿using System;
using System.Buffers;
using System.Threading;
using System.Threading.Tasks;

namespace WholeSlideImageLibrary.Formats.Dmetrix
{
    public class DmetrixImageIdentifier : IImageIdentifier
    {
        public string Name => "Dmetrix";

        public int HeaderSize => DmetrixFileHeader.MarshalStructureSize;

        public ValueTask<ImageSourceType> IdentifyAsync(FileSourceInfo fileInfo, FileSourceReader reader, ReadOnlyMemory<byte> header, CancellationToken cancellationToken = default)
        {
            if (!DmetrixFileHeader.TryParse(header.Span, out _))
            {
                return new ValueTask<ImageSourceType>(ImageSourceType.None);
            }
            return new ValueTask<ImageSourceType>(ImageSourceType.SingleImage);
        }

        public ValueTask<ImageSourceType> IdentifyAsync(DirectorySourceInfo directoryInfo, CancellationToken cancellationToken = default)
        {
            return new ValueTask<ImageSourceType>(ImageSourceType.None);
        }

        public ValueTask<WholeSlideImageCollection?> OpenImageCollectionAsync(FileSourceInfo fileInfo, FileSourceReader reader, CancellationToken cancellationToken = default)
        {
            return default;
        }

        public ValueTask<WholeSlideImageCollection?> OpenImageCollectionAsync(DirectorySourceInfo directoryInfo, CancellationToken cancellationToken = default)
        {
            return default;
        }

        public async ValueTask<WholeSlideImage?> OpenSingleImageAsync(FileSourceInfo fileInfo, FileSourceReader reader, CancellationToken cancellationToken = default)
        {
            if (fileInfo is null)
            {
                throw new ArgumentNullException(nameof(fileInfo));
            }
            if (reader is null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            byte[] buffer = ArrayPool<byte>.Shared.Rent(HeaderSize);
            try
            {
                int bytesRead = await reader.ReadAsync(0, buffer.AsMemory(0, HeaderSize), cancellationToken).ConfigureAwait(false);
                if (DmetrixFileHeader.TryParse(buffer.AsSpan(0, bytesRead), out DmetrixFileHeader header))
                {
                    return new DmetrixWholeSlideImage(fileInfo, header);
                }

                return null;
            }
            finally
            {
                ArrayPool<byte>.Shared.Return(buffer);
            }
        }

        public ValueTask<WholeSlideImage?> OpenSingleImageAsync(DirectorySourceInfo directoryInfo, CancellationToken cancellationToken = default)
        {
            return default;
        }
    }
}
